/* Moderator	: helpbygrace ( helpbygrace_AT_gmail.com ) */
#ifndef _PROC_H_
#define _PROC_H_

#include "common.h"

/* Register structure
     각 프로세서 내부에 들어가는 레지스터의 모음.
     union구조로, gpr, spr, cpr등에 대한 독립적인 저장공간을 가진다.
*/
typedef union
{
  word	val;

  /* Process Status register */
  struct
    {
      unsigned	mode:2;
      unsigned	ie:1;
      unsigned	v:1;
      unsigned	c:1;
      unsigned	z:1;
      unsigned	n:1;
      unsigned	de:1;
      unsigned	reserved:8;

      unsigned	prev_mode:2;
      unsigned	prev_ie:1;
      unsigned	prev_v:1;
      unsigned	prev_c:1;
      unsigned	prev_z:1;
      unsigned	prev_n:1;
      unsigned	prev_de:1;
      unsigned	prev_reserved:8;
    } ps_format;

  /* Debugger register */
  struct
    {
      unsigned	reserved:24;
      unsigned	wb3:1;
      unsigned	wb2:1;
      unsigned	wb1:1;
      unsigned	wb0:1;
      unsigned	bp3:1;
      unsigned	bp2:1;
      unsigned	bp1:1;
      unsigned	bp0:1;
    } dbgc_format;
  struct
    {
      unsigned	en:1;
      unsigned	reserved:31;
    } dbg_control;
      
} reg_t;

/* Processor Control structure
     현재 프로세스의 상태를 저장하고있는 구조체이다.
     프로세스는 제어부에 의해 일반적인 상태, delay slot 상태,
     nop 상태일 수 있다.
*/
typedef enum
{
  proc_control_none=0,
  proc_control_nop=1,
  proc_control_branch_slot=2,
} proc_control_t;

/* Process Event list enumeration
     process가 실행 도중 발생할 event 를 담고 있는 값이다.
     event_handler를 통해 해결해야 할 list를 담고 있다.
*/
typedef enum
{
  proc_event_none,

  reset_interrupt,
  page_fault,
  data_abort,
  undefined_instruction,
  software_interrupt,
  ext_interrupt,
  cop_interrupt,
  debug_interrupt,
} proc_event_t;

/* Processor structure
     프로세서 하나의 내부 데이터 모음이다.
     다중 프로세서로 변환을 쉽게 하기 위해 각 프로세서별 데이터는
     이 구조체에 모아져서 함수 호출시 같이 넘겨준다.
*/
typedef struct
{
  reg_t	*gpr;	/* general purpose register file */
  reg_t *spr;	/* program counter와, program status register */
  reg_t *dbg;	/* debug information register */

  proc_control_t	control;
  proc_event_t		event;
  word			br_pc;

  /* Count
       실행된 명령어 갯수, 실행된 clock사이클 수,
       메모리 접근 수, 의 정보를 담고있다.
  */
  word			c_insn;
  word			c_cycle;
  word			c_mem;
} proc_t;


/* Interface
     외부에 공개되는 함수 선언부
*/
#define GPR_SIZE	16
#define SPR_SIZE	2
#define	_GPR(PROC,I)	((PROC)->gpr[(I)])
#define	_SPR(PROC,I)	((PROC)->spr[(I)])

#define	GPR(PROC,I)	(_GPR(PROC,I).val)
#define	SPR(PROC,I)	(_SPR(PROC,I).val)

#define GPR_RA(PROC)	(GPR(PROC,15))
#define SPR_PC(PROC)	(SPR(PROC,0))
#define _SPR_PS(PROC)	(_SPR(PROC,1))

#define PS_MODE(PROC)	((_SPR_PS(PROC)).ps_format.mode)
#define PS_IE(PROC)	((_SPR_PS(PROC)).ps_format.ie)
#define PS_V(PROC)	((_SPR_PS(PROC)).ps_format.v)
#define PS_C(PROC)	((_SPR_PS(PROC)).ps_format.c)
#define PS_Z(PROC)	((_SPR_PS(PROC)).ps_format.z)
#define PS_N(PROC)	((_SPR_PS(PROC)).ps_format.n)
#define PS_DE(PROC)	((_SPR_PS(PROC)).ps_format.de)

/* Debug Unit 관련 설정 */
#define BP_SIZE		8
#define WP_SIZE		4
#define DBG_SIZE	(2*BP_SIZE + 2*WP_SIZE)

#define	_DBG(PROC,I)	((PROC)->dbg[(I)])
#define	BCR(PROC,I)	((_DBG(PROC,2*(I)).dbg_control))
#define BVR(PROC,I)	((_DBG(PROC,2*(I)+1).val))
#define WCR(PROC,I)	((_DBG(PROC,2*(BP_SIZE+(I))).dbg_control))
#define WVR(PROC,I)	((_DBG(PROC,2*(BP_SIZE+(I))).val))
#define BPE(PROC,I)	(BCR(PROC,I).en)
#define	WPE(PROC,I)	(WCR(PROC,I).en)

int init_proc (proc_t *proc);
int fini_proc (proc_t *proc);

/*!Notify Event to processor */
void	event	(proc_t		*proc,
		 proc_event_t	e );
#endif /* _PROC_H_ */
